#include "tm1668.h"
#include "SC_Init.h"

// #define TM1668_KEY_DIO_PIN P21
// #define TM1668_KEY_CLK_PIN P22
// #define TM1668_KEY_STB_PIN P20

// #define TM1668_DISP_DIO_PIN P25
// #define TM1668_DISP_CLK_PIN P24
// #define TM1668_DISP_STB_PIN P26
extern void RGBReduceLightSwitch(uint8_t en);
#define TM1668_KEY_DIO_PIN P25
#define TM1668_KEY_CLK_PIN P24
#define TM1668_KEY_STB_PIN P26

#define TM1668_DISP_DIO_PIN P21
#define TM1668_DISP_CLK_PIN P22
#define TM1668_DISP_STB_PIN P20

#define TM1668_CMD_MODE1 0x00
#define TM1668_CMD_DATA1 0x40
#define TM1668_CMD_ADDR1 0xC0
#define TM1668_CMD_DIS_ON 0x88
#define TM1668_CMD_DIS_OFF 0x80

#define TM1668_DAT_BUF_SIZE 10
#define TM1668_KEY_BUF_SIZE 16

unsigned char xdata tm1668KeyDatBuf[TM1668_KEY_BUF_SIZE] = {0};
unsigned char xdata tm1668DispDatBuf[TM1668_DAT_BUF_SIZE] = {0};
unsigned char tm1668_key_brightness = 1;
unsigned char tm1668_disp_brightness = 1;

unsigned char xdata tm1668KeyFlushFlag = 1;
unsigned char xdata tm1668DispFlushFlag = 1;

unsigned char code dispNum[14] =
{
		0x3f, // 0b00111111, 0
		0x06, // 0b00000110,  1
		0x5b, // 0b01011011,  2
		0x4f, // 0b01001111,  3
		0x66, // 0b01100110,  4
		0x6D, // 0b01101101,  5
		0x7D, // 0b01111101,  6
		0x07, // 0b00000111,  7
		0x7F, // 0b01111111,  8
		0x6F, // 0b01101111   9
		0x80, // 0b10000000   . 10
		0x76, // 0b01110110   H  11
		0x00, // 0b00000000   NULL  12
		0x40, // 0b01000000   - 13
};

unsigned char tm1668_num_set(unsigned char index, unsigned char value)
{
	if (index > 3)
		return 1;

	if (value > 14)
		return 1;

	tm1668DispFlushFlag = 1;
	tm1668DispDatBuf[8 - index * 2] &= 0x80;
	tm1668DispDatBuf[8 - index * 2] |= dispNum[value];
	//	tm1668DispDatBuf[index*2+1] = (dispNum[value]&0x60)>>5;
	return 0;
}

unsigned char tm1668_num_val_set(unsigned int value)
{
	if(value == 0xffff){
		tm1668_num_set(0, 13);
		tm1668_num_set(1, 13);
		tm1668_num_set(2, 13);		
	}else{
		if (value > 999){
			value = 999;
		}

		tm1668_num_set(0, value / 100 % 10);
		tm1668_num_set(1, value / 10 % 10);
		tm1668_num_set(2, value % 10);
		
	}
	
	tm1668DispDatBuf[8 - 0 * 2] |= 0x80;
	tm1668DispDatBuf[8 - 1 * 2] |= 0x80;
	tm1668DispDatBuf[8 - 2 * 2] |= 0x80;
	tm1668DispDatBuf[8 - 3 * 2] |= 0x80;
	
	return 0;
}

unsigned char only_num_val_set(unsigned char value,unsigned char index)
{
	unsigned char i = 0; 
	if (value > 999)
		value = 999;
	if(index == 1)
	{
		tm1668_num_set(1, value);
		tm1668DispDatBuf[8 - 0 * 2] &= 0x80;
		tm1668DispDatBuf[8 - 2 * 2] &= 0x80;
	}
	else if(index == 2){
		tm1668_num_set(0, value / 100 % 10);
		tm1668_num_set(1, value / 10 % 10);;
		tm1668DispDatBuf[8 - 2 * 2] &= 0x80;
	}
	else if(index == 3){
		tm1668_num_set(0, value / 100 % 10);
		tm1668_num_set(1, value / 10 % 10);
		tm1668_num_set(2, value % 10);
	}
	tm1668DispDatBuf[8 - 0 * 2] &= ~(0x01 << 7);
	tm1668DispDatBuf[8 - 1 * 2] &= ~(0x01 << 7);
	tm1668DispDatBuf[8 - 2 * 2] &= ~(0x01 << 7);
	tm1668DispDatBuf[8 - 3 * 2] &= ~(0x01 << 7);
	return 0;
}

void tm1668_num_disp_off(void)
{
	tm1668DispDatBuf[8 - 0 * 2] = dispNum[12];
	tm1668DispDatBuf[8 - 1 * 2] = dispNum[12];
	tm1668DispDatBuf[8 - 2 * 2] = dispNum[12];
	tm1668DispDatBuf[8 - 3 * 2] = dispNum[12];

	tm1668DispFlushFlag = 1;
}

/*
typedef enum{
	ePanelFlagPower = 0,
	ePanelFlagTimer,
	ePanelFlagDisinfect,
	ePanelFlagMode,
	ePanelFlagTimingHour,

	ePanelFlagMax,
}ePANEL_FLAG;
*/

unsigned char tm1668_key_test(unsigned char value)
{
	tm1668KeyFlushFlag = 1;
	tm1668DispDatBuf[0] = 0;
	tm1668DispDatBuf[0] |= (0x01 << value);
	return 0;
}

unsigned char tm1668_flag_set(ePANEL_FLAG index, unsigned char value)
{
	if (index > ePanelFlagMax)
		return 1;

	tm1668KeyFlushFlag = 1;
	tm1668DispFlushFlag = 1;
	switch (index)
	{
	case ePanelFlagPower:
		if (value)
		{	
			tm1668KeyDatBuf[4] &= ~(0x01 << 5);
			tm1668KeyDatBuf[4] &= ~(0x01 << 6);
			tm1668KeyDatBuf[4] &= ~(0x01 << 7);
			
			tm1668KeyDatBuf[6] |= (0x01 << 5);
			tm1668KeyDatBuf[6] |= (0x01 << 6);
			tm1668KeyDatBuf[6] |= (0x01 << 7);
		}
		else
		{		
			tm1668KeyDatBuf[4] |= (0x01 << 5);
			tm1668KeyDatBuf[4] |= (0x01 << 6);
			tm1668KeyDatBuf[4] |= (0x01 << 7);
			
			tm1668KeyDatBuf[6] &= ~(0x01 << 5);
			tm1668KeyDatBuf[6] &= ~(0x01 << 6);
			tm1668KeyDatBuf[6] &= ~(0x01 << 7);
		}
		break;
	case ePanelFlagTimer:
		if (value)
		{
			tm1668KeyDatBuf[7] |= (0x01 << 1); // time
			tm1668KeyDatBuf[7] |= (0x01 << 3);
			tm1668KeyDatBuf[7] |= (0x01 << 4);

		}
		else
		{
			tm1668KeyDatBuf[7] &= ~(0x01 << 3); // time
			tm1668KeyDatBuf[7] &= ~(0x01 << 4);
			tm1668KeyDatBuf[7] &= ~(0x01 << 1);
		}
		break;
	case ePanelFlagDisinfect:
		if (value)
		{
			// tm1668KeyDatBuf[1] |= (0x01 << 0);
			tm1668DispDatBuf[2] |= (0x01 << 1);
			tm1668DispDatBuf[0] |= (0x01 << 1);
		}
		else
		{
			// tm1668KeyDatBuf[1] &= ~(0x01 << 0);
			tm1668DispDatBuf[2] &= ~(0x01 << 1);
			tm1668DispDatBuf[0] &= ~(0x01 << 1);
		}
		break;
		
	case ePanelFlagIon:
		if (value)
		{
			tm1668DispDatBuf[2] |= (0x01 << 0);
			tm1668DispDatBuf[0] |= (0x01 << 0);
		}
		else
		{
			// tm1668KeyDatBuf[1] &= ~(0x01 << 0);
			tm1668DispDatBuf[2] &= ~(0x01 << 0);
			tm1668DispDatBuf[0] &= ~(0x01 << 0);
		}
		break;
		
		
	case ePanelFlagMode:

		tm1668DispDatBuf[2] &= ~(0x01 << 2);
		tm1668DispDatBuf[2] &= ~(0x01 << 3);
		tm1668DispDatBuf[2] &= ~(0x01 << 4);
		tm1668DispDatBuf[0] &= ~(0x01 << 2);
		tm1668DispDatBuf[0] &= ~(0x01 << 3);
		tm1668DispDatBuf[0] &= ~(0x01 << 4);
		switch (value)
		{
		case 1://sleep
			tm1668DispDatBuf[0] |= (0x01 << 2);
			tm1668DispDatBuf[2] |= (0x01 << 2);
			break;
		case 2://normal
			tm1668DispDatBuf[0] |= (0x01 << 3);
			tm1668DispDatBuf[2] |= (0x01 << 3);
			break;
		case 3://automation
			tm1668DispDatBuf[0] |= (0x01 << 4);
			tm1668DispDatBuf[2] |= (0x01 << 4);
			break;
		case 4:
			tm1668DispDatBuf[0] |= (0x01 << 2);
			tm1668DispDatBuf[0] |= (0x01 << 3);
			tm1668DispDatBuf[0] |= (0x01 << 4);
			tm1668DispDatBuf[2] |= (0x01 << 2);
			tm1668DispDatBuf[2] |= (0x01 << 3);
			tm1668DispDatBuf[2] |= (0x01 << 4);
			break;
		default:
			// tm1668DispDatBuf[0] &= ~ (0x01 << 6);
			break;
		}
		break;

	case ePanelFlagFilter:
		tm1668DispDatBuf[2] &= ~(0x01 << 5);
		tm1668DispDatBuf[2] &= ~(0x01 << 6);
		if (value)
		{
			tm1668DispDatBuf[2] |= (0x01 << 5);
			tm1668DispDatBuf[2] |= (0x01 << 6);
		}
		else
		{
			tm1668DispDatBuf[2] &= ~(0x01 << 5);
			tm1668DispDatBuf[2] &= ~(0x01 << 6);
		}
		break;
		
	case ePanelFlagWifi:
		tm1668DispDatBuf[0] &= ~(0x01 << 5);
		tm1668DispDatBuf[0] &= ~(0x01 << 6);
		if (value)
		{
			tm1668DispDatBuf[0] |= (0x01 << 5);
			tm1668DispDatBuf[0] |= (0x01 << 6);
		}
		else
		{
			tm1668DispDatBuf[0] &= ~(0x01 << 5);
			tm1668DispDatBuf[0] &= ~(0x01 << 6);
		}
		break;

	case ePanelFlagBGL:
		if (value)
		{
			tm1668KeyDatBuf[7] |= (0x01 << 1); // mode 
			tm1668KeyDatBuf[7] |= (0x01 << 3);
			tm1668KeyDatBuf[7] |= (0x01 << 4); // mode 
			tm1668KeyDatBuf[15] |= (0x01 << 1);
			tm1668KeyDatBuf[15] |= (0x01 << 3);
			tm1668KeyDatBuf[15] |= (0x01 << 4);
			
		}
		else
		{
			tm1668KeyDatBuf[7] &= ~(0x01 << 1); // mode 
			tm1668KeyDatBuf[7] &= ~(0x01 << 3);
			tm1668KeyDatBuf[7] &= ~(0x01 << 4);
			tm1668KeyDatBuf[15] &= ~(0x01 << 1); 
			tm1668KeyDatBuf[15] &= ~(0x01 << 3);
			tm1668KeyDatBuf[15] &= ~(0x01 << 4);
		}
		break;

	default:
		break;
	}
	return 0;
}

unsigned char tm1668_Key_single_set(ePANEL_FLAG index, unsigned char value)
{
	if (index > ePanelFlagMax)
		return 1;
	tm1668KeyFlushFlag = 1;
	switch (index)
	{
	case ePanelFlagPower:
		if (value)
		{
			tm1668KeyDatBuf[4] &= ~(0x01 << 5);
			tm1668KeyDatBuf[4] &= ~(0x01 << 6);
			tm1668KeyDatBuf[4] &= ~(0x01 << 7);
			
			tm1668KeyDatBuf[6] |= (0x01 << 5);
			tm1668KeyDatBuf[6] |= (0x01 << 6);
			tm1668KeyDatBuf[6] |= (0x01 << 7);
		
		}
		else
		{
			tm1668KeyDatBuf[4] |= (0x01 << 5);
			tm1668KeyDatBuf[4] |= (0x01 << 6);
			tm1668KeyDatBuf[4] |= (0x01 << 7);
			
			tm1668KeyDatBuf[6] &= ~(0x01 << 5);
			tm1668KeyDatBuf[6] &= ~(0x01 << 6);
			tm1668KeyDatBuf[6] &= ~(0x01 << 7);	
		}
		break;

	case ePanelFlagIon:
		if (value)
		{
			tm1668KeyDatBuf[9] |= (0x01 << 3);
			tm1668KeyDatBuf[9] |= (0x01 << 4);
			tm1668KeyDatBuf[9] |= (0x01 << 1);
			
			tm1668KeyDatBuf[3] &= ~(0x01 << 3);
			tm1668KeyDatBuf[3] &= ~(0x01 << 4);
			tm1668KeyDatBuf[3] &= ~(0x01 << 1);
		}
		else
		{
			tm1668KeyDatBuf[9] &= ~(0x01 << 3);
			tm1668KeyDatBuf[9] &= ~(0x01 << 4);
			tm1668KeyDatBuf[9] &= ~(0x01 << 1);
			
			tm1668KeyDatBuf[3] |= (0x01 << 3);
			tm1668KeyDatBuf[3] |= (0x01 << 4);
			tm1668KeyDatBuf[3] |= (0x01 << 1);
		}
		break;

	case ePanelFlagDisinfect:
		if (value)
		{
			tm1668KeyDatBuf[8] |= (0x01 << 5); 
			tm1668KeyDatBuf[8] |= (0x01 << 6);
			tm1668KeyDatBuf[8] |= (0x01 << 7);

			tm1668KeyDatBuf[2] &= ~(0x01 << 5);
			tm1668KeyDatBuf[2] &= ~(0x01 << 6);
			tm1668KeyDatBuf[2] &= ~(0x01 << 7);
		}
		else
		{
			tm1668KeyDatBuf[8] &= ~(0x01 << 5); 
			tm1668KeyDatBuf[8] &= ~(0x01 << 6);
			tm1668KeyDatBuf[8] &= ~(0x01 << 7);

			tm1668KeyDatBuf[2] |= (0x01 << 5); 
			tm1668KeyDatBuf[2] |= (0x01 << 6);
			tm1668KeyDatBuf[2] |= (0x01 << 7);
		}
		break;
		
	case ePanelFlagMode:
		if (value)
		{
			tm1668KeyDatBuf[7] |= (0x01 << 1); // mode 
			tm1668KeyDatBuf[7] |= (0x01 << 3);
			tm1668KeyDatBuf[7] |= (0x01 << 4); // mode 
			tm1668KeyDatBuf[15] &= ~(0x01 << 1); 
			tm1668KeyDatBuf[15] &= ~(0x01 << 3);
			tm1668KeyDatBuf[15] &= ~(0x01 << 4);
			
		}
		else
		{
			tm1668KeyDatBuf[7] &= ~(0x01 << 1); // mode 
			tm1668KeyDatBuf[7] &= ~(0x01 << 3);
			tm1668KeyDatBuf[7] &= ~(0x01 << 4);
			tm1668KeyDatBuf[15] |= (0x01 << 1);
			tm1668KeyDatBuf[15] |= (0x01 << 3);
			tm1668KeyDatBuf[15] |= (0x01 << 4);
		}
		break;

	default:
		break;
	}
	
	return 0;
}

void tm1668_flag_all_control(unsigned char value)
{
	uint8_t i = 0;
	tm1668KeyFlushFlag = 1;
	tm1668DispFlushFlag = 1;
	if (value == 0)
	{
		for (i = 0; i < TM1668_DAT_BUF_SIZE; i++)
		{
			tm1668DispDatBuf[i] = 0;
		}
		for (i = 0; i < TM1668_KEY_BUF_SIZE; i++)
		{
			tm1668KeyDatBuf[i] = 0;
		}
	}
	else
	{
		for (i = 0; i < TM1668_DAT_BUF_SIZE; i++)
		{
			tm1668DispDatBuf[i] = 0xff;
		}
		for (i = 0; i < TM1668_KEY_BUF_SIZE; i++)
		{
			tm1668KeyDatBuf[i] = 0xff;
		}
		
		tm1668KeyDatBuf[4] &= ~(0x01 << 5);
		tm1668KeyDatBuf[4] &= ~(0x01 << 6);
		tm1668KeyDatBuf[4] &= ~(0x01 << 7);
	}
}

void tm1668DelayMs(unsigned int ms)
{
	unsigned int delay_i = 0, delay_j;
	for (delay_j = 0; delay_j < ms; delay_j++)
	{
		for (delay_i = 0; delay_i < 100; delay_i++)
		{
			_nop_();
			_nop_();
		}
	}
}

/*tm1668 key driver begin*/
void tm1668_key_send_start(void)
{
	TM1668_KEY_STB_PIN = 1;
	TM1668_KEY_CLK_PIN = 1;
	_nop_();
	_nop_();
	_nop_();
	TM1668_KEY_STB_PIN = 0;
}

void tm1668_key_send_end(void)
{
	TM1668_KEY_STB_PIN = 1;
	_nop_();
}

void tm1668_key_send_byte(unsigned char value)
{
	unsigned char i = 0;

	for (i = 0; i < 8; i++)
	{
		TM1668_KEY_CLK_PIN = 0;
		if (((value >> i) & 0x01) == 0x01)
			TM1668_KEY_DIO_PIN = 1;
		else
			TM1668_KEY_DIO_PIN = 0;
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		TM1668_KEY_CLK_PIN = 1;
		_nop_();
		_nop_();
	}
}

void tm1668_key_send_cmd(unsigned char value)
{

	unsigned char i = 0;

	tm1668_key_send_start();
	tm1668_key_send_byte(value);
	tm1668_key_send_end();
}

void tm1668_key_send_data(void)
{
	uint8_t j = 0;
	tm1668_key_send_start();

	tm1668_key_send_byte(TM1668_CMD_ADDR1);

	for (j = 0; j < TM1668_KEY_BUF_SIZE; j++)
	{
		tm1668_key_send_byte(tm1668KeyDatBuf[j]);
	}

	tm1668_key_send_end();
}

unsigned char tm1668_key_light_set(unsigned char value)
{
	if (value > 8)
		return 1;

	if (value != 0)
	{
		tm1668_key_brightness = value;
		tm1668_key_send_cmd(0x87 + value);
	}
	else
	{
		tm1668_key_send_cmd(0x80);
	}

	return 0;
}

/*tm1668 key driver end*/

/*tm1668 disp driver begin*/
void tm1668_disp_send_start(void)
{
	TM1668_DISP_STB_PIN = 1;
	TM1668_DISP_CLK_PIN = 1;
	_nop_();
	_nop_();
	_nop_();
	TM1668_DISP_STB_PIN = 0;
}

void tm1668_disp_send_end(void)
{
	TM1668_DISP_STB_PIN = 1;
	_nop_();
}

void tm1668_disp_send_byte(unsigned char value)
{
	unsigned char i = 0;

	for (i = 0; i < 8; i++)
	{
		TM1668_DISP_CLK_PIN = 0;
		if (((value >> i) & 0x01) == 0x01)
			TM1668_DISP_DIO_PIN = 1;
		else
			TM1668_DISP_DIO_PIN = 0;
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		TM1668_DISP_CLK_PIN = 1;
		_nop_();
		_nop_();
	}
}

void tm1668_disp_send_cmd(unsigned char value)
{

	unsigned char i = 0;

	tm1668_disp_send_start();
	tm1668_disp_send_byte(value);
	tm1668_disp_send_end();
}

void tm1668_disp_send_data(void)
{
	uint8_t j = 0;
	tm1668_disp_send_start();

	tm1668_disp_send_byte(TM1668_CMD_ADDR1);

	for (j = 0; j < TM1668_DAT_BUF_SIZE; j++)
	{
		tm1668_disp_send_byte(tm1668DispDatBuf[j]);
	}

	tm1668_disp_send_end();
}

unsigned char tm1668_disp_light_set(unsigned char value)
{
	if (value > 8)
		return 1;

	if (value != 0)
	{
		tm1668_disp_brightness = value;
		tm1668_disp_send_cmd(0x87 + value);
	}
	else
	{
		tm1668_disp_send_cmd(0x80);
	}

	return 0;
}

/*tm1668 disp driver end*/

void tm1668GpioInit(void)
{
	/*key pannel*/
	GPIO_Init(GPIO2, GPIO_PIN_4, GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_5, GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_6, GPIO_MODE_OUT_PP);
	/*display pannel*/
	GPIO_Init(GPIO2, GPIO_PIN_0, GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_1, GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_2, GPIO_MODE_OUT_PP);
}

void tm1668_led_flush_handle(void)
{
	if (tm1668KeyFlushFlag == 1)
	{
		tm1668_key_send_data();
		tm1668KeyFlushFlag = 0;
	}

	if (tm1668DispFlushFlag == 1)
	{
		tm1668_disp_send_data();
		tm1668DispFlushFlag = 0;
	}
}

void tm1668Init(void)
{
	tm1668GpioInit();
	tm1668_key_send_cmd(TM1668_CMD_MODE2);
	tm1668_key_send_cmd(TM1668_CMD_DATA1);
	tm1668_disp_send_cmd(TM1668_CMD_MODE2);
	tm1668_disp_send_cmd(TM1668_CMD_DATA1);
	RGBReduceLightSwitch(1);
	// tm1668DispDatBuf[0] = 0xff;
	// tm1668DispDatBuf[1] = 0xff;
}